package com.demo.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.entity.*;
import com.demo.entity.Vo.PatientVo;
import com.demo.enums.*;
import com.demo.jwt.JwtTokenUtil;
import com.demo.mapper.*;
import com.demo.response.Result;
import com.demo.service.IMessageService;
import com.demo.service.IPatientService;
import com.demo.websocket.WebSocketServer;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * 病患信息表 服务实现类
 *
 * @author zm
 * @since 2020-11-26
 */
@Service
@Slf4j
@Transactional
public class PatientServiceImpl extends ServiceImpl<PatientMapper, Patient> implements IPatientService {
    @Resource
    PatientMapper patientMapper;
    @Resource
    VtePreventiveMapper vtePreventiveMapper;
    @Resource
    VtePreventiveDoctorAdviceMapper vtePreventiveDoctorAdviceMapper;
    @Resource
    UserMapper userMapper;
    @Autowired
    IMessageService messageService;
    @Autowired
    WebSocketServer socketServer;
    @Resource
    PhysicalPreventionLogMapper physicalPreventionLogMapper;
    @Resource
    DepartmentMapper departmentMapper;
    @Resource
    PatientTransitionMapper patientTransitionMapper;
    @Resource
    VtePreventiveDoctorAdviceMapper doctorAdviceMapper;
    @Resource
    DvtDiagnoseMapper dvtDiagnoseMapper;
    @Resource
    DischargeSummaryMapper dischargeSummaryMapper;

    /**
     * @param pageNumber  页码
     * @param pageSize    每页数量
     * @param admissionId 住院号
     * @param deptType    科室ID
     * @param patientId   患者姓名
     * @param vestType    患者归属：1.我的
     * @param status      2.出院
     * @param deptSn      科室/病区ID
     * @return
     */
    @Override
    public Result patientList(Integer pageNumber, Integer pageSize, String admissionId, Integer deptType, String patientId, Integer vestType, Integer status, Integer deptSn, String wardId) {

        deptType = null;
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        Integer uid = JwtTokenUtil.decodeTokenUserId(request.getHeader("token"));
        if (pageNumber.equals(1)) {
            pageNumber = 0;
        } else {
            pageNumber = pageNumber.intValue() - 1;
            pageNumber = pageNumber.intValue() * pageSize.intValue();
        }
        User user = userMapper.getWorkId(uid);
        String workId = null;
        if (vestType != null) {
            workId = user.getWorkSn();
        }

        List<Integer> wardIdArray = new ArrayList<>();
        if (wardId.isEmpty()) {
            int[] deptArray = StrUtil.splitToInt(user.getUserDepartment(), ",");
            List<Department> deptList = departmentMapper.getDeptListByInDeptSn(deptArray);
            wardIdArray = deptList.stream().map(Department::getDeptMapping).collect(Collectors.toList());
        } else {
            wardIdArray.add(Integer.parseInt(wardId));
        }
        List<PatientVo> patientVoList = new ArrayList<>();
        Integer count = patientMapper.patientListCount(admissionId, deptType, patientId, vestType, status, deptSn, workId, wardIdArray);
        List<Patient> list = patientMapper.patientList(pageNumber, pageSize, admissionId, deptType, patientId, vestType, status, deptSn, workId, wardIdArray);
        for (Patient patient : list) {
            PatientVo patientVo = new PatientVo();
            BeanUtils.copyProperties(patient, patientVo);
            VtePreventive vtePreventive = vtePreventiveMapper.getPatientLastTime(patient.getPatientId());
            if (vtePreventive != null) {
                if (vtePreventive.getPreventiveType() != null) {
                    if (vtePreventive.getPreventiveType().equals(1)) {
                        patientVo.setNumberDanger("C" + vtePreventive.getPreventiveRiskScore());
                    } else {
                        patientVo.setNumberDanger("P" + vtePreventive.getPreventiveRiskScore());
                    }
                }

                VtePreventiveDoctorAdvice vtePreventiveDoctorAdviceIpc = getVtePreventiveDoctorAdviceIpc(patient.getPatientId());
                if (vtePreventiveDoctorAdviceIpc != null) {//原来的：vtePreventive.getPhysicalPrevention() != null
                    if (patient.getStatus() == PatientStatusEnum.CHU_YUAN.getValue()) {
                        patientVo.setPhysical(0);
                    } else {
                        QueryWrapper<PhysicalPreventionLog> queryWrapper = new QueryWrapper();
                        queryWrapper.select(new String[]{"end_time"});
                        queryWrapper.eq("patient_id", vtePreventive.getPatientId());
                        queryWrapper.orderByDesc("physical_prevention_id");
                        queryWrapper.last("limit 1");
                        PhysicalPreventionLog physicalPreventionLog = physicalPreventionLogMapper.selectOne(queryWrapper);
                        patientVo.setPhysical(1);
                        log.info("查询到物理治疗记录{}", physicalPreventionLog);
                        if (physicalPreventionLog != null) {
                            DateTime dateTime = DateUtil.parse(DateUtil.now(), "yyyy-MM-dd HH:mm:ss");
                            if (dateTime.before(physicalPreventionLog.getEndTime())) {
                                patientVo.setPhysical(2);
                            }
                        }
                    }
                }
                patientVo.setDanger(vtePreventive.getPreventiveRiskRank());
            }
            patientVoList.add(patientVo);
        }
        Integer pages = null;
        Integer sum2 = null;
        if (count != null) {
            pages = Integer.valueOf(count.intValue() / pageSize.intValue());
            sum2 = Integer.valueOf(count.intValue() % pageSize.intValue());
            if (sum2 != null) {
                pages = Integer.valueOf(pages.intValue() + 1);
            }
        }
        PageInfo<PatientVo> pageInfo = new PageInfo(patientVoList);
        pageInfo.setPages(pages.intValue());
        pageInfo.setTotal(count.intValue());
        if (pageNumber.equals(pages)) {
            pageInfo.setIsLastPage(false);
        } else {
            pageInfo.setIsLastPage(true);
        }
        return Result.success(pageInfo);
    }

    /**
     * 通过病患ID，获取名称
     *
     * @param id
     * @return
     */
    @Override
    public String vtePatievtName(Integer id) {
        QueryWrapper<Patient> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("patient_id", id);
        queryWrapper.select("patient_name");
        Patient patient = patientMapper.selectOne(queryWrapper);
        return patient.getPatientName();
    }

    /**
     * 新增病患信息
     *
     * @param patient
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = {RuntimeException.class, Error.class})
    public Map<String, String> addPatient(Patient patient) throws Exception {
        Map<String, String> map = new HashMap<>();
        QueryWrapper<Patient> queryWrapper = new QueryWrapper();
        queryWrapper.eq("his_patient_id", patient.getHisPatientId());
        List<Patient> inPatient = patientMapper.selectList((Wrapper) queryWrapper);
        if (inPatient.size() > 0) {
            throw new Exception("HIS系统病人编号不能重复");
        }
//        QueryWrapper<Patient> bedQueryWrapper = new QueryWrapper();
//        bedQueryWrapper.ne("status", PatientStatusEnum.CHU_YUAN.getValue());
//        bedQueryWrapper.eq("bed_id", patient.getBedId());
//        inPatient = patientMapper.selectList(bedQueryWrapper);
//        if (inPatient.size() > 0) {
//            throw new Exception("新入病人与在院病人床号不能重复");
//        }
        boolean flag = save(patient);
        if (flag == true) {
            map.put("code", "200");
            map.put("msg", "成功");
        }
        QueryWrapper<Patient> newQueryWrapper = new QueryWrapper();
        newQueryWrapper.eq("his_patient_id", patient.getHisPatientId());
        newQueryWrapper.last("limit 1");
        Patient newPatient = patientMapper.selectOne(newQueryWrapper);
        PatientTransition patientTransition = new PatientTransition();
        BeanUtils.copyProperties(patient, patientTransition);
        patientTransition.setChangeTime(new Date());
        patientTransition.setChangeType(patient.getStatus());
        patientTransition.setPatientId(newPatient.getPatientId());
        // 新增病人信息变动表
        patientTransitionMapper.insert(patientTransition);
        Map<String, Object> msgContent = new HashMap<>();
        msgContent.put("bed_id", patient.getBedId());
        msgContent.put("bed_name", patient.getBedName());
        msgContent.put("patient_name", patient.getPatientName());
        msgContent.put("dept_name", patient.getDeptName());
        msgContent.put("dept_sn", patient.getDeptSn());
        msgContent.put("message_text", String.format("该病人为%s病人，请进行<span style=\"color:red\">VTE风险评估</span>", PatientStatusEnum.getByValue(patient.getStatus()).getDesc()));
        messageService.sendMessageNotification(MessageRemindEnum.PING_GU_REMIND, newPatient, MessageSourceEnum.HIS_PUSH, msgContent, 0);
        log.info("----------------------------------------------------------------------------------------------------");
        msgContent.put("message_text", String.format("该病人为%s病人，请进行<span style=\"color:red\">DVT筛查</span>", PatientStatusEnum.getByValue(patient.getStatus()).getDesc()));
        messageService.sendMessageNotification(MessageRemindEnum.ZHEN_DUAN_REMIND, newPatient, MessageSourceEnum.HIS_PUSH, msgContent, 0);
        return map;
    }

    @Override
    public Patient selectPatientDesc(Integer patientId) {
        return patientMapper.selectById(patientId);
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = {RuntimeException.class, Error.class})
    public Result changPatientStatus(Integer hisPatientId, Integer status, Integer is_transition, PatientTransition patientTransition) throws Exception {
        log.info("转科数据为{}", patientTransition);
        QueryWrapper<Patient> queryWrapper = new QueryWrapper();
        queryWrapper.eq("his_patient_id", hisPatientId);
        queryWrapper.isNull("deleted_time");
        queryWrapper.last("limit 1");
        Patient inPatient = patientMapper.selectOne(queryWrapper);
        if (inPatient == null) {
            throw new Exception("HIS系统病人编号不存在");
        }
        boolean flag = true;
        patientTransition.setChangeTime(new Date());
        patientTransition.setPatientId(inPatient.getPatientId());
        String opportunity = "";
        if (is_transition.intValue() == 1) {
            if (status != null) {
                throw new Exception("转科不能病情状态变化");
            }
            QueryWrapper<Department> departmentQueryWrapper = new QueryWrapper();
            departmentQueryWrapper.eq("dept_sn", patientTransition.getDeptSn());
            departmentQueryWrapper.isNull("deleted_user_id");
            Department department = departmentMapper.selectOne(departmentQueryWrapper);
            patientTransition.setChangeType(PatientTransitionChangeTypeEnum.ZHUAN_KE.getValue());
            // 病情变化时新增病人变动信息表
            patientTransitionMapper.insert(patientTransition);
            patientMapper.updateByHisPatientId(hisPatientId, status, patientTransition.getAdmissionId(), patientTransition.getWardId(),
                    patientTransition.getBedId(), patientTransition.getMedicalLeader(), patientTransition.getMedicalLeaderName(),
                    patientTransition.getDoctorInCharge(), patientTransition.getDoctorInChargeName(), patientTransition.getHeadNurse(),
                    patientTransition.getHeadNurseName(), patientTransition.getNurseInCharge(), patientTransition.getNurseInChargeName(),
                    patientTransition.getHospitalDisttrictName(), patientTransition.getHospitalDisttrictId(), department.getDeptType(),
                    department.getDeptName(), department.getDeptSn(), department.getDeptAreaName());
            // 转科以后之前的所有未停止的医嘱停掉
            doctorAdviceMapper.stopUnStopAdvice(inPatient.getPatientId());
            // 更新以后查询最新的病人数据
            inPatient = patientMapper.selectOne(queryWrapper);
            opportunity = "该病人是新入病人";
        } else {
            if (status == null) {
                throw new Exception("病人状态不可为空");
            }
            if (inPatient.getStatus() == null) {
                throw new Exception("病人状态不可为空");
            }
            if (patientTransition.getChangeType() == inPatient.getStatus()) {
                throw new Exception("当前与病情变化后一样，无效操作");
            }
            BeanUtils.copyProperties(inPatient, patientTransition);
            patientTransition.setChangeType(status);
            // 病情变化时新增病人变动信息表
            patientTransitionMapper.insert(patientTransition);
            flag = patientMapper.updateStatus(status, hisPatientId);
        }

        if (status != null) {
            if (status != null && status == PatientStatusEnum.XIN_RU.getValue()) {
                opportunity = "初始被评为" + PatientStatusEnum.XIN_RU.getDesc() + "病人";
            } else if (status != null && status == PatientStatusEnum.SHU_HOU.getValue()) {
                opportunity = "初始被评为" + PatientStatusEnum.SHU_HOU.getDesc() + "病人";
            } else if (status != null && status == PatientStatusEnum.FEN_MIAN.getValue()) {
                opportunity = "初始被评为" + PatientStatusEnum.FEN_MIAN.getDesc() + "病人";
            } else if (status != null && status == PatientStatusEnum.CHU_YUAN.getValue()) {
                opportunity = PatientStatusEnum.CHU_YUAN.getDesc();
            }
        }

        Map<String, Object> msgContent = new HashMap<>();
        msgContent.put("bed_id", inPatient.getBedId());
        msgContent.put("bed_name", inPatient.getBedName());
        msgContent.put("patient_name", inPatient.getPatientName());
        msgContent.put("dept_name", inPatient.getDeptName());
        msgContent.put("dept_sn", inPatient.getDeptSn());
        inPatient.setStatus(status);
        if (status != null && status == PatientStatusEnum.CHU_YUAN.getValue()) {
            vtePreventiveDoctorAdviceMapper.updateStatusByPatientId(PreventiveDoctorAdviceStatusEnum.HAS_STOP.getValue(), inPatient.getPatientId());
            vtePreventiveDoctorAdviceMapper.updateStopTimeByPatientId(inPatient.getPatientId());
            msgContent.put("message_text", "该病人已经" + opportunity + "，请进行出院总结");
            messageService.sendMessageNotification(MessageRemindEnum.ZONG_JIE_REMIND, inPatient, MessageSourceEnum.HIS_PUSH, msgContent, 0);
        } else {
            msgContent.put("message_text", opportunity + "，请进行<span style=\"color:red\">VTE风险评估</span>");
            messageService.sendMessageNotification(MessageRemindEnum.PING_GU_REMIND, inPatient, MessageSourceEnum.HIS_PUSH, msgContent, 0);
            msgContent.put("message_text", opportunity + "，请进行<span style=\"color:red\">DVT筛查</span>");
            messageService.sendMessageNotification(MessageRemindEnum.ZHEN_DUAN_REMIND, inPatient, MessageSourceEnum.HIS_PUSH, msgContent, 0);
        }
        return Result.success(Boolean.valueOf(flag));
    }

    /**
     * 科室监控【患者列表】
     *
     * @param deptSn 病区/科室ID
     * @return
     */
    @Override
    public Result vteDepartmentMonitoring(Integer pageNumber, Integer pageSize, Integer deptSn) {
        Page page = new Page(pageNumber.intValue(), pageSize.intValue());
        QueryWrapper<Patient> queryWrapper = new QueryWrapper();
        queryWrapper.eq("dept_sn", deptSn);
        queryWrapper.ne("status", PatientStatusEnum.CHU_YUAN.getValue());//非出院患者
        IPage<Patient> iPage = patientMapper.selectPage(page, queryWrapper);
        List<Patient> list = iPage.getRecords();
        for (Patient patient : list) {
            // 根据病人 id，以及sign_time 医生签字开医嘱时间为不空 查询最后一次 vte 诊断记录
            QueryWrapper<VtePreventive> vtePreventiveQueryWrapper = new QueryWrapper();
            vtePreventiveQueryWrapper.eq("patient_id", patient.getPatientId());
            vtePreventiveQueryWrapper.and(qw -> qw.isNotNull("sign_time").or().isNotNull("risk_confirm_time"));
            vtePreventiveQueryWrapper.orderByDesc("vte_preventive_id");
            vtePreventiveQueryWrapper.last("limit 1 ");
            VtePreventive vtePreventive = vtePreventiveMapper.selectOne(vtePreventiveQueryWrapper);
            if (vtePreventive != null) {
                // vte 风险
                patient.setVteRisk(vtePreventive.getPreventiveRiskRank());
            }

            // 根据病人 id，以及sign_time 医生签字开医嘱时间为不空 查询最后一次 vte 诊断记录
            QueryWrapper<VtePreventive> vtePreventiveQueryWrapperBleed = new QueryWrapper();
            vtePreventiveQueryWrapperBleed.eq("patient_id", patient.getPatientId());
            vtePreventiveQueryWrapperBleed.isNotNull("sign_time");
            vtePreventiveQueryWrapperBleed.isNotNull("risk_confirm_time");
            vtePreventiveQueryWrapperBleed.orderByDesc("vte_preventive_id");
            vtePreventiveQueryWrapperBleed.last("limit 1 ");
            VtePreventive vtePreventiveBleed = vtePreventiveMapper.selectOne(vtePreventiveQueryWrapperBleed);
            if (vtePreventiveBleed != null) {
                // 出血风险
                JSONObject bleedObject = JSONUtil.parseObj(vtePreventiveBleed.getPreventiveTabooResult());
                if (bleedObject.containsKey("常见出血危险因素") || bleedObject.containsKey("外科手术危险因素") || bleedObject.containsKey("出血后果严重手术")) {
                    patient.setBleedingRisk(PatientBleedingRiskEnum.GAO_WEI.getValue());
                } else {
                    patient.setBleedingRisk(PatientBleedingRiskEnum.DI_WEI.getValue());
                }
            }

            QueryWrapper<VtePreventiveDoctorAdvice> vtePreventiveDoctorAdviceQueryWrapper = new QueryWrapper();
            vtePreventiveDoctorAdviceQueryWrapper.eq("patient_id", patient.getPatientId());
            vtePreventiveDoctorAdviceQueryWrapper.eq("status", PreventiveDoctorAdviceStatusEnum.UN_STOP.getValue());
            vtePreventiveDoctorAdviceQueryWrapper.eq("advise_type", VtePreventiveDoctorAdviceTypeEnum.YAO_WU.getValue());
            vtePreventiveDoctorAdviceQueryWrapper.isNull("deleted_time");
            vtePreventiveDoctorAdviceQueryWrapper.orderByDesc("doctor_advice_id");
            vtePreventiveDoctorAdviceQueryWrapper.last("limit 1 ");
            VtePreventiveDoctorAdvice vtePreventiveDoctorAdvice = doctorAdviceMapper.selectOne(vtePreventiveDoctorAdviceQueryWrapper);
            VtePreventiveDoctorAdvice vtePreventiveDoctorAdviceIpc = getVtePreventiveDoctorAdviceIpc(patient.getPatientId());

            //  预防措施
            if (vtePreventiveDoctorAdvice != null && vtePreventiveDoctorAdviceIpc != null) {
                patient.setPrecaution(PatientPrecautionEnum.WU_LI_AND_YAO_WU.getValue());
                continue;
            }
            if (vtePreventiveDoctorAdvice == null && vtePreventiveDoctorAdviceIpc != null) {
                patient.setPrecaution(PatientPrecautionEnum.WU_LI_PRECAUTION.getValue());
                continue;
            }
            if (vtePreventiveDoctorAdvice != null && vtePreventiveDoctorAdviceIpc == null) {
                patient.setPrecaution(PatientPrecautionEnum.FANG_GUI_CHANG_ZHI.getValue());
            }
        }
        PageInfo<Patient> pageInfo = new PageInfo(iPage.getRecords());
        pageInfo.setPages((int) iPage.getPages());
        pageInfo.setTotal(iPage.getTotal());
        return Result.success(pageInfo);
    }

    private VtePreventiveDoctorAdvice getVtePreventiveDoctorAdviceIpc(Integer patientId) {
        QueryWrapper<VtePreventiveDoctorAdvice> vtePreventiveDoctorAdviceQueryWrapperIpc = new QueryWrapper();
        vtePreventiveDoctorAdviceQueryWrapperIpc.eq("patient_id", patientId);
        vtePreventiveDoctorAdviceQueryWrapperIpc.eq("status", PreventiveDoctorAdviceStatusEnum.UN_STOP.getValue());
        vtePreventiveDoctorAdviceQueryWrapperIpc.eq("advise_type", VtePreventiveDoctorAdviceTypeEnum.WU_LI_IPC.getValue());
        vtePreventiveDoctorAdviceQueryWrapperIpc.isNull("deleted_time");
        vtePreventiveDoctorAdviceQueryWrapperIpc.orderByDesc("doctor_advice_id");
        vtePreventiveDoctorAdviceQueryWrapperIpc.last("limit 1 ");
        VtePreventiveDoctorAdvice vtePreventiveDoctorAdviceIpc = doctorAdviceMapper.selectOne(vtePreventiveDoctorAdviceQueryWrapperIpc);
        return vtePreventiveDoctorAdviceIpc;
    }

    public Result getPatientArchives(Integer his_patient_id, Integer patient_id) throws Exception {
        Map<String, Object> archives = new HashMap<>();
        QueryWrapper<Patient> queryWrapper = new QueryWrapper();
        if (his_patient_id != null) {
            queryWrapper.eq("his_patient_id", his_patient_id);
        }
        if (patient_id != null) {
            queryWrapper.eq("patient_id", patient_id);
        }
        Patient patient = patientMapper.selectOne(queryWrapper);
        archives.put("patient_info", patient);
        if (his_patient_id == null) {
            his_patient_id = patient.getHisPatientId();
        }
        QueryWrapper<VtePreventive> vtePreventiveQueryWrapper = new QueryWrapper();
        vtePreventiveQueryWrapper.eq("patient_id", patient_id);
        List<VtePreventive> vtePreventives = vtePreventiveMapper.selectList(vtePreventiveQueryWrapper);
        archives.put("vte_preventive", vtePreventives);
        QueryWrapper<DvtDiagnose> dvtDiagnoseQueryWrapper = new QueryWrapper();
        dvtDiagnoseQueryWrapper.eq("patient_id", patient_id);
        List<DvtDiagnose> dvtDiagnoseList = dvtDiagnoseMapper.selectList(dvtDiagnoseQueryWrapper);
        archives.put("dvt_diagnose", dvtDiagnoseList);
        QueryWrapper<DischargeSummary> dischargeSummaryQueryWrapper = new QueryWrapper();
        dischargeSummaryQueryWrapper.eq("patient_id", patient_id);
        DischargeSummary dischargeSummary = dischargeSummaryMapper.selectOne(dischargeSummaryQueryWrapper);
        archives.put("discharge_summary", dischargeSummary);
        return Result.success(archives);
    }

}
